use std::time::SystemTime;

// 判断质数(暴力版)
fn is_prime_number_powerful(n: i32) -> bool {
    if n > 2 {
        for i in 2..(n - 1) {
            if n % i == 0 {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}

// 判断质数(暴力优化版)
fn is_prime_number_powerful_majorization(n: i32) -> bool {
    if n % 2 == 0 {
        n == 2
    } else if n > 2 {
        for i in (3..(n - 1)).step_by(2) {
            if n % i == 0 {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}

// 判断质数(优雅版)
fn is_prime_number_elegant(n: i32) -> bool {
    if n % 2 == 0 {
        n == 2
    } else if n > 2 {
        for i in (3..((n as f64).sqrt() as i32)).step_by(2) {
            if n % i == 0 {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}

// 判断质数(优雅优化版)
fn is_prime_number_elegant_majorization(n: i32) -> bool {
    if n % 2 == 0 {
        n == 2
    } else if n == 3 {
        return true;
    } else if n > 3 {
        // equals to n >=5
        let m = n % 6;
        if m != 1 && m != 5 {
            return false;
        }
        for i in (5..=((n as f64).sqrt() as i32)).step_by(6) {
            if n % i == 0 || n % (i + 2) == 0 {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}

// 找质数(循环外就过滤掉偶数的部份，减少循环执行的次数)
fn get_prime_number<F>(a: i32, b: i32, is_prime: F) -> Vec<i32>
where
    F: Fn(i32) -> bool,
{
    let mut result = Vec::new();
    for n in a..=b {
        if n < 4 {
            result.push(n);
        } else if n % 2 != 0 {
            if is_prime(n) {
                result.push(n);
            }
        }
    }
    result
}

fn main() {
    let a = 0;
    let b = 10000;
    // 测试各个版本的耗时
    let system_time = SystemTime::now();
    get_prime_number(a, b, is_prime_number_powerful);
    println!(
        "powerful version: {:?} s",
        system_time.elapsed().unwrap().as_secs_f64()
    );

    let system_time = SystemTime::now();
    get_prime_number(a, b, is_prime_number_powerful_majorization);
    println!(
        "powerful majorization version: {:?} s",
        system_time.elapsed().unwrap().as_secs_f64()
    );

    let system_time = SystemTime::now();
    get_prime_number(a, b, is_prime_number_elegant);
    println!(
        "elegant version: {:?} s",
        system_time.elapsed().unwrap().as_secs_f64()
    );

    let system_time = SystemTime::now();
    get_prime_number(a, b, is_prime_number_elegant_majorization);
    println!(
        "elegant majorization version: {:?} s",
        system_time.elapsed().unwrap().as_secs_f64()
    );
}
